#pragma once

#include "noncopyable.h"
#include "Callbacks.h"
#include "EventLoopThreadPool.h"
#include "InetAddress.h"
#include "Acceptor.h"
#include "EventLoop.h"
#include "TcpConnection.h"
#include "Buffer.h"

#include <string>
#include <memory>
#include <functional>
#include <atomic>
#include <unordered_map>

class EventLoop;
class Acceptor;
class EventLoopThreadPool;
class InetAddress;

class TcpServer : noncopyable
{
public:
    using ThreadInitCallbcak = std::function<void(EventLoop *)>;
    using Functor = std::function<void()>;

    enum Option
    {
        kNoReusePort,
        kReusePort
    };

    TcpServer(EventLoop *loop,
              const InetAddress &listenAddr,
              const std::string &nameArg,
              Option option = kNoReusePort);
    ~TcpServer();

    // 设置subloop的个数
    void setThreadNum(int numThreads);

    void setThreadInitCallback(const ThreadInitCallbcak &cb) { threadInitCallbcak_ = cb; }
    void setConnectionCallback(const ConnectionCallback &cb) { connectionCallback_ = cb; }
    void setMessageCallback(const MessageCallback &cb) { messageCallback_ = cb; }
    void setWriteCompleteCallback(const WriteCompleteCallback &cb) { writeCompleteCallback_ = cb; }

    // 设置超时销毁时间函数
    void EnableInactiveRelease(int timeout)
    {
        timeout_ = timeout;
        enableInactiveRelease_ = true;
    }

    // 开启baseloop的监听
    void start();

    //添加定时任务的接口
    void runAfter(const Functor& task, int delay);

private:
    void newConnection(int sockfd, const InetAddress &peerAddr);
    // 移除connections_中的存储的连接，因为他的类型是shared_ptr，会计数
    void removeConnection(const TcpConnectionPtr &conn);
    void removeConnectionInLoop(const TcpConnectionPtr &conn);

    void runAfterInLoop(const Functor& task, int delay);

    using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>;

    EventLoop *loop_; // baseloop/mainloop
    const std::string ipPort_;
    const std::string name_;
    std::unique_ptr<Acceptor> acceptor_;
    std::shared_ptr<EventLoopThreadPool> threadPool_;

    ConnectionCallback connectionCallback_;       // 有新连接时的回调
    MessageCallback messageCallback_;             // 有读写消息时的回调
    WriteCompleteCallback writeCompleteCallback_; // 消息发送完成后的回调
    ThreadInitCallbcak threadInitCallbcak_;       // subloop线程初始化的函数
    std::atomic<int> started_;
    /**
     * 连接的非活跃销毁这个定时任务的key值是TcpConnection对象的名称，即 name_-ipport#nextConnId_
     * 我们收动添加的定时任务的key值是to_string(taskId_), 且由baseLoop执行
     */
    int nextConnId_;            // 连接序号
    int taskId_;                //手动添加的定时任务的序号
    ConnectionMap connevtions_; // 保存TcpConnectionPtr与连接名称的键值对

    int timeout_;                   // 非活跃链接的统计时间
    int enableInactiveRelease_;  //标识是否启动非活跃连接超时销毁
};